{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Finding centroids\n",
    "\n",
    "In this example, we're going to find a \"centroid\" (representitive structure) for a group of conformations. This group might potentially come from clustering, using method like Ward hierarchical clustering.\n",
    "\n",
    "Note that there are many possible ways to define the centroids. This is just one."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "from __future__ import print_function\n",
    "%matplotlib inline\n",
    "import mdtraj as md\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Load up a trajectory to use for the example."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "traj = md.load('ala2.h5')\n",
    "print(traj)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Lets compute all pairwise rmsds between conformations."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "atom_indices = [a.index for a in traj.topology.atoms if a.element.symbol != 'H']\n",
    "distances = np.empty((traj.n_frames, traj.n_frames))\n",
    "for i in range(traj.n_frames):\n",
    "    distances[i] = md.rmsd(traj, traj, i, atom_indices=atom_indices)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The algorithim we're going to use is relatively simple:\n",
    "- Compute all of the pairwise RMSDs between the conformations. This is O(N^2), so it's not going to\n",
    "  scale extremely well to large datasets.\n",
    "- Transform these distances into similarity scores. Our similarities will calculated as\n",
    "  $$ s_{ij} = e^{-\\beta \\cdot d_{ij} / d_\\text{scale}} $$\n",
    "  where $s_{ij}$ is the pairwise similarity, $d_{ij}$ is the pairwise distance, and $d_\\text{scale}$ is the standard deviation of\n",
    "  the values of $d$, to make the computation scale invariant.\n",
    "- Then, we define the centroid as\n",
    "  $$ \\text{argmax}_i \\sum_j s_{ij} $$\n",
    "\n",
    "Using $\\beta=1$, this is implemented with the following code:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "beta = 1\n",
    "index = np.exp(-beta*distances / distances.std()).sum(axis=1).argmax()\n",
    "print(index)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "centroid = traj[index]\n",
    "print(centroid)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
